package com.lg.redis.simple;

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.lg.exception.RedisConfigException;
import com.lg.shiro.RedisContext;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Repository
public class RedisClient implements InitializingBean, DisposableBean {

	private static final Logger logger = LoggerFactory.getLogger(RedisClient.class);
	private JedisPool jedis;
	/**
	 * 
	 */
	@Value("${redis.host}")
	private String host;
	@Value("${redis.port}")
	private Integer port;
	/**
	 * ��Ⱥ��½����
	 */
	//@Value(value="${redis.password}")
	private String password;
	@Value("${redis.connectionTimeout}")
	private Integer connectionTimeout;
	@Value("${redis.soTimeout}")
	private Integer soTimeout;
	@Value("${redis.maxAttempts}")
	private Integer maxAttempts;
	//jedispoolConfig
	/**
	 * ���������
	 */
	@Value("${redis.maxTotal}")
	private Integer maxTotal;
	/**
	 * ������������
	 */
	@Value("${redis.maxIdle}")
	private Integer maxIdle;
	/**
	 * ��С����������
	 */
	@Value("${redis.minIdle}")
	private Integer minIdle;
	/**
	  * ��ȡ����ʱ�����ȴ�������,С����:������ȷ����ʱ��,Ĭ��-1
	 */
	@Value("${redis.maxWaitMillis}")
	private Long maxWaitMillis;
    /**
        * ÿ���ͷ����ӵ������Ŀ
     */
	@Value("${redis.numTestsPerEvictionRun}")
	private Integer numTestsPerEvictionRun;
	/**
	 * �ͷ����ӵ�ɨ���������룩
	 */
	@Value("${redis.timeBetweenEvictionRunsMillis}")
	private Integer timeBetweenEvictionRunsMillis;
	/**
	 * ������С����ʱ�� 
	 */
	@Value("${redis.minEvictableIdleTimeMillis}")
	private Long minEvictableIdleTimeMillis;
	/**
	 *  ���ӿ��ж�ú��ͷ�, ������ʱ��>��ֵ �� ��������>������������ ʱֱ���ͷ� 
	 */
	@Value("${redis.softMinEvictableIdleTimeMillis}")
	private Long softMinEvictableIdleTimeMillis;
	/**
	 *  �ڻ�ȡ���ӵ�ʱ������Ч��, Ĭ��false 
	 */
	@Value("${redis.testOnBorrow}")
	private boolean testOnBorrow;
	/**
	 * �ڿ���ʱ�����Ч��, Ĭ��false 
	 */
	@Value("${redis.testWhileIdle}")
	private boolean testWhileIdle;
	/**
	 * �ڹ黹��poolʱ���Ƿ���ǰ����validate����
	 */
	@Value("${redis.testOnReturn}")
	private boolean testOnReturn;
	/**
	  * ���Ӻľ�ʱ�Ƿ�����, false���쳣,ture����ֱ����ʱ, Ĭ��true 
	 */
	@Value("${redis.blockWhenExhausted}")
	private boolean blockWhenExhausted;
	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		try {
			jedis.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public Jedis getJedis() {
		if (jedis == null) {
			try {
				afterPropertiesSet();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				logger.error("redis init faile:" + e);
				throw new RedisConfigException();
			}
		}
		if(RedisContext.get()==null) {
			Jedis resource = jedis.getResource();
			RedisContext.set(resource);
			return resource;
		}
		return RedisContext.get();
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		if (StringUtils.isEmpty(host)) {
			String erro = "redis host isEmpty";
			logger.error(erro);
			throw new RedisConfigException(erro);
		}
		if (StringUtils.isEmpty(port)) {
			String erro = "redis port isEmpty";
			logger.error(erro);
			throw new RedisConfigException(erro);
		}
		JedisPoolConfig poolConfig = new JedisPoolConfig();
		poolConfig.setMaxTotal(maxTotal==null ? 150 :maxTotal);
		poolConfig.setMaxIdle(maxIdle== null ? 30 : maxIdle);
		poolConfig.setMinIdle(minIdle == null ? 10:minIdle );
		poolConfig.setMaxWaitMillis(maxWaitMillis== null ? 3000l:maxWaitMillis);
		poolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun == null ? 100:numTestsPerEvictionRun);
		poolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis == null ? 3000l : timeBetweenEvictionRunsMillis);
		poolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis  == null ? 1800000l : minEvictableIdleTimeMillis);
		poolConfig.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis  == null ? 10000 : softMinEvictableIdleTimeMillis);
		poolConfig.setTestOnBorrow(testOnBorrow);
		poolConfig.setTestOnReturn(testOnReturn);
		poolConfig.setBlockWhenExhausted(blockWhenExhausted);
		jedis =   new JedisPool(poolConfig, host,port, connectionTimeout);

	}

}
